<script setup lang="ts">
import {
  get,
  omit,
} from 'lodash-es'
import {
  ref,
  toValue,
  useSlots,
  watchEffect,
} from 'vue'

interface IItem {
  label: string
  value: any
}

interface IProps {
  options?: IItem[]
  api?: (...args: any) => any
  apiParams?: Record<string, any>
  apiResultLabelField?: string
  apiResultValueField?: string
  apiResultDataField?: string
  format?: (res: any) => IItem[]
}

defineOptions({ name: 'BaseSelect' })

const {
  options,
  api,
  apiParams = {},
  apiResultLabelField = 'label',
  apiResultValueField = 'value',
  apiResultDataField = 'result',
  format,
} = defineProps<IProps>()

const emit = defineEmits(['success', 'error'])

const modelValue = defineModel()

const list = ref<IItem[]>([])

const slots = useSlots() as any
const slotNames = Object.keys(slots)

async function setList() {
  if (!api)
    return

  try {
    const res = await api(apiParams)

    if (format) {
      list.value = format(res)
      return
    }

    list.value = get(res, apiResultDataField)?.map((item: any) => ({
      ...item,
      label: item[apiResultLabelField],
      value: item[apiResultValueField],
    })) ?? []

    emit('success', toValue(list))
  }
  catch (error) {
    console.log('error>>>>>', error)
    emit('error', error)
  }
}

watchEffect(() => {
  list.value = options || []
})

setList()
</script>

<template>
  <ElSelect
    v-model="modelValue"
    clearable
    collapse-tags
    collapse-tags-tooltip
    v-bind="$attrs"
  >
    <ElOption
      v-for="item in list"
      :key="item.value"
      :label="item.label"
      :value="item.value"
    >
      <slot
        v-if="slots.default"
        v-bind="item"
      />
    </ElOption>

    <template
      v-for="slotName in omit(slotNames, 'default')"
      :key="slotName"
    >
      <slot
        :name="slotName"
      />
    </template>
  </ElSelect>
</template>
